package Model;

import java.util.Date;
import java.util.ArrayList;
import java.text.SimpleDateFormat;
import java.lang.Iterable;
import java.util.Iterator;

import Model.States.*;
import data.RowDataGateway;

public class Task implements Iterable<Task>, PersistentObject {

    private String name;
    private boolean done;
    private Date dueDate;
    private String type;
    protected ArrayList<Task> mTodo; /** Tasks list */
    protected RowDataGateway datainterface;
    protected ArrayList<RowDataGateway> childrenDataInterfaces;
    protected PObjectState state; //member variables important for state-pattern
    
    //storing States. Used whenever theirs a switch in patterns.
    protected NewState newState;
    protected OldCleanState oldcleanstate;
    protected OldDeleteState olddeletestate;
    protected OldDirtyState olddirtystate;

    /**
     * Constructor which creates a task with the following parameters
     *
     * @param iTaskName
     * @param iDueDate
     * @param iType
     */
    public Task(String iTaskName, Date iDueDate, String iType) {
        name = iTaskName;
        dueDate = iDueDate;
        type = iType;
        done = false;
        mTodo = new ArrayList<Task>();
        childrenDataInterfaces = new ArrayList<RowDataGateway>();
        
        datainterface = new RowDataGateway(iTaskName, iDueDate, iType, done, null, childrenDataInterfaces);

        newState = new NewState(); //just created state, not in DB
        oldcleanstate = new OldCleanState(); //from DB and unmodified
        olddeletestate = new OldDeleteState(); // from DB and Ready to-be deleted.
        olddirtystate = new OldDirtyState(); //from DB and modified. 
        
        state = newState; //just created Task.
        this.commit();
    }

    /**
     * Copy constructor
     *
     * @param task
     */
    public Task(Task task) {
        this.name = task.getName();
        this.type = task.getType();
        this.dueDate = task.getDueDate();
        mTodo = new ArrayList<Task>(); // TODO ****NOT PROPER. Must perform deep-copy of sub-tasks...
        childrenDataInterfaces = new ArrayList<RowDataGateway>();
        

       	datainterface = new RowDataGateway(this.name, this.dueDate, this.type , done, null, childrenDataInterfaces);

        
        newState = new NewState();
        oldcleanstate = new OldCleanState();
        olddeletestate = new OldDeleteState();
        olddirtystate = new OldDirtyState();
        
        state = newState; //just created Task.
        this.commit();
    }

    /**
     * Sets this instances' name to empty string ("")
     *
     * @param name
     */
    public void removeName(String name) {
        this.name = "";
        datainterface.setName("");
        state = olddirtystate;
    }


    /**
     * Sets the status of the current task as done
     *
     * @param done
     */
    public void setDone(boolean done) {
        this.done = done;
        datainterface.setDone(done); //updates Data Gateway
        state = olddirtystate;
        this.registerDirty();
    }

    /**
     * Set the name of the current task
     *
     * @param n
     */
    public void setName(String n) {
        this.name = n;
        datainterface.setName(n);
        state = olddirtystate;
        this.registerDirty();
    }

    /**
     * Get the name of the current task
     *
     * @return
     */
    public String getName() {
        return this.name;
    }

    /**
     * Get the due date of the task
     *
     * @return
     */
    public Date getDueDate() {
        return dueDate;
    }

    /**
     * Get the status of the current task
     *
     * @return
     */
    public boolean getDone() {
        return this.done;
    }

    /**
     * Get the type of the current task
     *
     * @return
     */
    public String getType() {
        return type;
    }
    
    

    public RowDataGateway getDatainterface() 
    {
		return datainterface;
	}

	public void setDatainterface(RowDataGateway datainterface) 
	{
		this.datainterface = datainterface;
	}

	public ArrayList<RowDataGateway> getChildrenDataInterfaces() 
	{
		return childrenDataInterfaces;
	}

	public void setChildrenDataInterfaces(
			ArrayList<RowDataGateway> childrenDataInterfaces) 
	{
		this.childrenDataInterfaces = childrenDataInterfaces;
	}

	/**
     * Return the task information as a string.
     *
     * @return
     */
    public String toString() {
        String str = new String();
        str = "[";
        str += name;
        str += "|";
        str += dueDate;
        str += "|";
        str += type;
        str += "|";
        str += done ? "done" : "notdone"; 
        str += "]";
        return str;
    }
    
    
    /**
     * Returns the due date for single tasks, 
     * Interval for periodic tasks
     * or "Complex" for complex tasks
     * @return
     */
    public String getDateString()
    {


    	if(null != dueDate)
    	{
	     	// Format date to yyyy-mm-dd
    		SimpleDateFormat wFormat = new SimpleDateFormat("yyyy-MM-dd");
    		return wFormat.format(dueDate);
    	}
    	else
    	{
    		return "No date";
    	}
    }
    
    /**
     * Returns the list of sub-tasks
     * @return
     */
    public ArrayList<Task> getSubtasks()
    {
    	return mTodo;    	
    }

    /**
     * Returns a iterator for the Task. Assume Iterator is being returned from the most top-top father task of the tree and not a sub-tasks iterator.
     * This would be useless and make the search useless.
     * @return
     */
    public Iterator<Task> iterator()
    {
        TaskTreeIterator iterateTasks; //reference to iterator that is YET to be created, based on to-be-checked properties.

        if(type.equals("Single"))  //if single task, then itterator should only have 1 item to itterate through, which is the task itself.
        {
            iterateTasks = new TaskTreeIterator(this,"Single");
            return iterateTasks;
        }

        else if (type.equals("Periodic"))
        {
            iterateTasks = new TaskTreeIterator(this,"Periodic");
            return iterateTasks;
        }

        else if (type.equals("Complex"))
        {

            iterateTasks = new TaskTreeIterator(this,"Complex");
            return iterateTasks;
        }

        else //should probably throw exception.... ?
            return null;
    }

    /**
     *
     */
    public void registerDirty()
    {
        state.registerDirty(this);
    }

    /**
    *
    */
    public void remove()
    {
        state.remove(this);
    }

    /**
     *
     */
    public void commit()
    {
        state.commit(this);
    }
    
    /**
    * Set the State of the Task
    */
    public void setState(String state)
    {
    	if(state.equals("newstate"))
    	{
    		this.state = newState;
    	}
    	
    	else if(state.equals("olddirtystate"))
    	{
    		this.state = olddirtystate;
    	}
    	
    	else if(state.equals("oldcleanstate"))
    	{
    		this.state = oldcleanstate;
    	}
    	
    	else if(state.equals("olddeletestate"))
    	{
    		this.state = olddeletestate;
    	}
    }

}
